/*
* AST.cpp
*
* ABSTRACT SYNTAX TREE
* Aqui presentes as classes que compõem a Árvore de Sintaxe Abstrata(codigo intermediario)
*/

#include "AST.hpp"
#include "Visitor.hpp"
#include "SymbolTable.hpp"
#include <stdlib.h>

/********************************************************************
*              Implementação da Classe node_Program                 *
********************************************************************/
node_Program :: node_Program(node_ClassList *ClassList){
    this->classList = ClassList;
}

node_Program :: ~node_Program(){
    if(this->classList) delete this->classList;
}

int node_Program :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_ClassList               *
********************************************************************/
node_ClassList :: node_ClassList(char* ClassName, char* extendedClassName, node_LocalDecl *FirstDecl, node_ClassList *NextClass, int line){
    this->className = ClassName;
    this->extendedClassName = extendedClassName;
    this->firstDecl = FirstDecl;
    this->nextClass = NextClass;
    this->line = line;
}

node_ClassList :: ~node_ClassList(){
    if(this->className) free(this->className);
    if(this->extendedClassName) free(this->extendedClassName);
    if(this->firstDecl) delete this->firstDecl;
    if(this->nextClass) delete this->nextClass;
}

int node_ClassList :: acceptVisitor(Visitor *v){
   return v->visit(this);
}

/********************************************************************
*              Implementação da Classe node_LocalDecl               *
********************************************************************/
node_LocalDecl :: node_LocalDecl(node_LocalDecl *nextDecl){
    this->nextDecl = nextDecl;
}

node_LocalDecl :: ~node_LocalDecl(){
    if(this->nextDecl) delete this->nextDecl;
}

/********************************************************************
*              Implementação da Classe node_MethodList              *
********************************************************************/
node_MethodList :: node_MethodList(char *MethodName, node_Type *ReturnType, node_VarList *ParamList, node_VarList *LocalVarList, node_StmtList *stmtList, node_LocalDecl *NextDecl, int line) : node_LocalDecl(NextDecl){
    this->methodName = MethodName;
    this->returnType = ReturnType;
    this->paramList = ParamList;
    this->localVarList = LocalVarList;
    this->stmtList = stmtList;
    this->line = line;
}

node_MethodList :: ~node_MethodList(){
    if(this->methodName) free(this->methodName);
    if(this->returnType) delete this->returnType;
    if(this->paramList) delete this->paramList;
    if(this->localVarList) delete this->localVarList;
    if(this->stmtList) delete this->stmtList;
}

int node_MethodList :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_VarList                 *
********************************************************************/
node_VarList :: node_VarList(node_NameDecl *VarName, node_LocalDecl *nextDecl) : node_LocalDecl(nextDecl){
    this->VarName = VarName;
}

node_VarList :: ~node_VarList(){
    if(this->VarName) delete this->VarName;
}

int node_VarList :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_Call                    *
********************************************************************/
node_Call :: node_Call(node_Name *CallMethod, int line){
    this->callMethod = CallMethod;
    this->line = line;
}

node_Call :: ~node_Call(){
    if(this->callMethod) delete this->callMethod;
}

int node_Call :: acceptVisitor(Visitor *v){
   return v->visit(this);
}

/********************************************************************
*              Implementação da Classe node_VarListStmt             *
********************************************************************/
node_VarListStmt :: node_VarListStmt(node_VarList *VarList){
    this->varList = VarList;
}

node_VarListStmt :: ~node_VarListStmt(){
    if(this->varList) delete this->varList;
}

int node_VarListStmt :: acceptVisitor(Visitor *v){
   return v->visit(this->varList);
}

/********************************************************************
*              Implementação da Classe node_Assign                  *
********************************************************************/
node_Assign :: node_Assign(node_Name *Name, node_Exp *AssignmentExp, int line){
    this->Name = Name;
    this->assignmentExp = AssignmentExp;
    this->line = line;
}

node_Assign :: ~node_Assign(){
    if(this->Name) delete this->Name;
    if(this->assignmentExp) delete this->assignmentExp;
}

int node_Assign :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_Return                  *
********************************************************************/
node_Return :: node_Return(node_Exp *Exp, int line){
    this->exp = Exp;
    this->line = line;
}

node_Return :: ~node_Return(){
    if(this->exp) delete this->exp;
}

int node_Return :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_Read                    *
********************************************************************/
node_Read :: node_Read(node_Exp *Exp, int line){
    this->exp = Exp;
    this->line = line;
}

node_Read :: ~node_Read(){
    if(this->exp) delete this->exp;
}

int node_Read :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_Printl                  *
********************************************************************/
node_Println :: node_Println(node_ExpList *ExpList, int line){
    this->expList = ExpList;
    this->line = line;
}

node_Println :: ~node_Println(){
    if(this->expList) delete this->expList;
}

int node_Println :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_If                      *
********************************************************************/
node_If :: node_If(node_Exp *Condition, node_StmtList *StmtList, node_StmtList *ElseStmtList, int line){
    this->condition = Condition;
    this->stmtList = StmtList;
    this->elseStmtList = ElseStmtList;
    this->line = line;
}

node_If :: ~node_If(){
    if(this->condition) delete this->condition;
    if(this->stmtList) delete this->stmtList;
    if(this->elseStmtList) delete this->elseStmtList;
}

int node_If :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_While                   *
********************************************************************/
node_While :: node_While(node_Exp *Condition, node_StmtList *StmtList, int line){
    this->condition = Condition;
    this->stmtList = StmtList;
    this->line = line;
}

node_While :: ~node_While(){
    if(this->condition) delete this->condition;
    if(this->stmtList) delete this->stmtList;
}

int node_While :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_StmtList                *
********************************************************************/
node_StmtList :: node_StmtList(node_Stmt *Stmt, node_StmtList *NextStmt){
    this->stmt = Stmt;
    this->nextStmt = NextStmt;
}

node_StmtList :: ~node_StmtList(){
    if(this->stmt) delete this->stmt;
    if(this->nextStmt) delete this->nextStmt;
}

int node_StmtList :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_New                     *
********************************************************************/
node_New :: node_New(node_Type *Type, node_Exp *ArrayLength, int line){
    this->type = Type;
    this->arrayLengthExp = ArrayLength;
    this->line = line;
}

node_New :: ~node_New(){
    if(this->type) delete this->type;
    if(this->arrayLengthExp) delete this->arrayLengthExp;
}

int node_New :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_Sign                    *
********************************************************************/
node_Sign :: node_Sign(int Sign, node_Exp *Exp, int line){
    this->sign = Sign;
    this->exp = Exp;
    this->line = line;
}

node_Sign :: ~node_Sign(){
    if(this->exp) delete this->exp;
}

int node_Sign :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_Not                     *
********************************************************************/
node_Not :: node_Not(node_Exp *Exp, int line){
    this->exp = Exp;
    this->line = line;
}

node_Not :: ~node_Not(){
    if(this->exp) delete this->exp;
}

int node_Not :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_Bitwise                 *
********************************************************************/
node_BitwiseOP :: node_BitwiseOP(int BitOp, node_Exp *LeftExp, node_Exp *RightExp, int line){
    this->bitOp = BitOp;
    this->leftExp = LeftExp;
    this->rightExp = RightExp;
    this->line = line;
}

node_BitwiseOP :: ~node_BitwiseOP(){
    if(this->leftExp) delete this->leftExp;
    if(this->rightExp) delete this->rightExp;
}

int node_BitwiseOP :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_BooleanOp               *
********************************************************************/
node_BooleanOP :: node_BooleanOP(int BoolOp, node_Exp *LeftExp, node_Exp *RightExp, int line){
    this->boolOp = BoolOp;
    this->leftExp = LeftExp;
    this->rightExp = RightExp;
    this->line = line;
}

node_BooleanOP :: ~node_BooleanOP(){
    if(this->leftExp) delete this->leftExp;
    if(this->rightExp) delete this->rightExp;
}
int node_BooleanOP :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_BinOp                   *
********************************************************************/
node_BinOp :: node_BinOp(int BinOp, node_Exp *LeftExp, node_Exp *RightExp, int line){
    this->binOp = BinOp;
    this->leftExp = LeftExp;
    this->rightExp = RightExp;
    this->line = line;
}

node_BinOp :: ~node_BinOp(){
    if(this->leftExp) delete this->leftExp;
    if(this->rightExp) delete this->rightExp;
}

int node_BinOp :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_Bin2Op                  *
********************************************************************/
node_Bin2Op :: node_Bin2Op(int Bin2Op, node_Exp *LeftExp, node_Exp *RightExp, int line){
    this->bin2Op = Bin2Op;
    this->leftExp = LeftExp;
    this->rightExp = RightExp;
    this->line = line;
}

node_Bin2Op :: ~node_Bin2Op(){
    if(this->leftExp) delete this->leftExp;
    if(this->rightExp) delete this->rightExp;
}

int node_Bin2Op :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*            Implementação da Classe node_RelationalOP              *
********************************************************************/
node_RelationalOP :: node_RelationalOP(int RelOp, node_Exp *LeftExp, node_Exp *RightExp, int line){
    this->relOp = RelOp;
    this->leftExp = LeftExp;
    this->rightExp = RightExp;
    this->line = line;
}

node_RelationalOP :: ~node_RelationalOP(){
    if(this->leftExp) delete this->leftExp;
    if(this->rightExp) delete this->rightExp;
}

int node_RelationalOP :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*            Implementação da Classe node_Number                    *
********************************************************************/
node_Number :: node_Number(int Type, char *Number, int line){
    this->type = Type;
    this->number = Number;
    this->line = line;
}

node_Number :: ~node_Number(){
    if(this->number) free(this->number);
}

int node_Number :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*            Implementação da Classe node_Logic                     *
********************************************************************/
node_Logic :: node_Logic(int Logic, int line){
    this->logic = Logic;
    this->line = line;
}

node_Logic :: ~node_Logic(){}

int node_Logic :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*            Implementação da Classe node_Literal                   *
********************************************************************/
node_Literal :: node_Literal(char *Literal, int line){
    this->literal = Literal;
    this->line = line;
}

node_Literal :: ~node_Literal(){
    if(this->literal) free(this->literal);
}

int node_Literal :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*              Implementação da Classe node_NameExp                 *
********************************************************************/
node_NameExp :: node_NameExp(node_Name *Name){
    this->Name = Name;
}

node_NameExp :: ~node_NameExp(){
    if(this->Name) delete this->Name;
}

int node_NameExp :: acceptVisitor(Visitor *v){
    return v->visit(this->Name);
}


/********************************************************************
*            Implementação da Classe node_Name                      *
********************************************************************/
node_Name :: node_Name(char* VarName, bool length, bool isThis, node_ExpList* SentParamsExpList, node_Name* NextName, bool isArray, node_Exp* index, int line){
    this->name = VarName;
    this->length = length;
    this->isThis = isThis;
    this->sentParamsExpList = SentParamsExpList;
    this->nextName = NextName;
    this->isArray = isArray;
    this->index = index;
    this->line = line;
    this->isMethod = false;
    this->tabLink = NULL;
    this->tabLinkType = 0;
}

node_Name :: ~node_Name(){
    if(this->name) free(this->name);
    if(this->sentParamsExpList) delete this->sentParamsExpList;
    if(this->nextName) delete this->nextName;
    if(this->index) delete this->index;
}

int node_Name :: acceptVisitor(Visitor *v){
    return v->visit(this);
}


/********************************************************************
*            Implementação da Classe node_NameDecl                  *
********************************************************************/
node_NameDecl :: node_NameDecl(node_Type *varType, char* varName, int line){
    this->varType = varType;
    this->varName = varName;
    this->line = line;
}

node_NameDecl :: ~node_NameDecl(){
    if(this->varType) delete this->varType;
    if(this->varName) free(this->varName);
}

int node_NameDecl :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*            Implementação da Classe node_Type                      *
********************************************************************/
node_Type :: node_Type(char *ClassName, int Primitivetype, bool isArray){
    this->className = ClassName;
    this->primitiveType = Primitivetype;
    this->isArray = isArray;
}

node_Type :: ~node_Type(){
    if(this->className) free(this->className);
}

int node_Type :: acceptVisitor(Visitor *v){
   return v->visit(this);
}


/********************************************************************
*            Implementação da Classe node_ExpList                   *
********************************************************************/
node_ExpList :: node_ExpList(node_Exp *Exp, node_ExpList *NextExp){
    this->exp = Exp;
    this->nextExp = NextExp;
}

node_ExpList :: ~node_ExpList(){
    if(this->exp) delete this->exp;
    if(this->nextExp) delete this->nextExp;
}

int node_ExpList :: acceptVisitor(Visitor *v){
   return v->visit(this);
}
